;
;  PROGRAM:  MKDIR
;  VERSION:  1.2
;  AUTHOR:  RICHARD CONN
;  DATE:  17 Jan 83
;  PREVIOUS VERSIONS:  1.1 (15 Jan 83), 1.0 (14 Jan 83)
;
VERS	EQU	12

;
;	MKDIR is used to create named directory files.  It allows the user
; to read and edit them.  It is fully integrated into the ZCPR2 system.
;
;	Forms of the MKDIR command are:
;		MKDIR			<-- Enter System
;		MKDIR //		<-- Get Help
;		MKDIR filename.typ	<-- Enter System with selected file
;

;
;  CP/M Constants
;
cpm	equ	0	; base
bdose	equ	cpm+5
fcb	equ	cpm+5ch
tbuff	equ	cpm+80h
cr	equ	0dh
lf	equ	0ah

;
;  SYSLIB Routines
;
	ext	print,zgpins,putud,getud,logud,retud,zfname,moveb
	ext	cin,cout,crlf,caps,compb
	ext	fi0$open,f0$get,fi0$close
	ext	fo0$open,f0$put,fo0$close
	ext	bbline,padc,initfcb,cline,zpfind,codend
	ext	sort

;
;	This program is Copyright (c) 1982, 1983 by Richard Conn
;	All Rights Reserved
;
;	ZCPR2 and its utilities, including this one, are released
; to the public domain.  Anyone who wishes to USE them may do so with
; no strings attached.  The author assumes no responsibility or
; liability for the use of ZCPR2 and its utilities.
;
;	The author, Richard Conn, has sole rights to this program.
; ZCPR2 and its utilities may not be sold without the express,
; written permission of the author.
;

;
;  Branch to Start of Program
;
	jmp	start

;
;******************************************************************
;
;  SINSFORM -- ZCPR2 Utility Standard General Purpose Initialization Format
;
;	This data block precisely defines the data format for
; initial features of a ZCPR2 system which are required for proper
; initialization of the ZCPR2-Specific Routines in SYSLIB.
;

;
;  EXTERNAL PATH DATA
;
EPAVAIL:
	DB	0FFH	; IS EXTERNAL PATH AVAILABLE? (0=NO, 0FFH=YES)
EPADR:
	DW	40H	; ADDRESS OF EXTERNAL PATH IF AVAILABLE

;
;  INTERNAL PATH DATA
;
INTPATH:
	DB	0,0	; DISK, USER FOR FIRST PATH ELEMENT
			; DISK = 1 FOR A, '$' FOR CURRENT
			; USER = NUMBER, '$' FOR CURRENT
	DB	0,0
	DB	0,0
	DB	0,0
	DB	0,0
	DB	0,0
	DB	0,0
	DB	0,0	; DISK, USER FOR 8TH PATH ELEMENT
	DB	0	; END OF PATH

;
;  MULTIPLE COMMAND LINE BUFFER DATA
;
MCAVAIL:
	DB	0FFH	; IS MULTIPLE COMMAND LINE BUFFER AVAILABLE?
MCADR:
	DW	0FF00H	; ADDRESS OF MULTIPLE COMMAND LINE BUFFER IF AVAILABLE

;
;  DISK/USER LIMITS
;
MDISK:
	DB	4	; MAXIMUM NUMBER OF DISKS
MUSER:
	DB	31	; MAXIMUM USER NUMBER

;
;  FLAGS TO PERMIT LOG IN FOR DIFFERENT USER AREA OR DISK
;
DOK:
	DB	0FFH	; ALLOW DISK CHANGE? (0=NO, 0FFH=YES)
UOK:
	DB	0FFH	; ALLOW USER CHANGE? (0=NO, 0FFH=YES)

;
;  PRIVILEGED USER DATA
;
PUSER:
	DB	10	; BEGINNING OF PRIVILEGED USER AREAS
PPASS:
	DB	'chdir',0	; PASSWORD FOR MOVING INTO PRIV USER AREAS
	DS	41-($-PPASS)	; 40 CHARS MAX IN BUFFER + 1 for ending NULL

;
;  CURRENT USER/DISK INDICATOR
;
CINDIC:
	DB	'$'	; USUAL VALUE (FOR PATH EXPRESSIONS)

;
;  DMA ADDRESS FOR DISK TRANSFERS
;
DMADR:
	DW	80H	; TBUFF AREA

;
;  NAMED DIRECTORY INFORMATION
;
NDRADR:
	DW	00000H	; ADDRESS OF MEMORY-RESIDENT NAMED DIRECTORY
NDNAMES:
	DB	64	; MAX NUMBER OF DIRECTORY NAMES
DNFILE:
	DB	'NAMES   '	; NAME OF DISK NAME FILE
	DB	'DIR'		; TYPE OF DISK NAME FILE

;
;  REQUIREMENTS FLAGS
;
EPREQD:
	DB	0FFH	; EXTERNAL PATH?
MCREQD:
	DB	000H	; MULTIPLE COMMAND LINE?
MXREQD:
	DB	0FFH	; MAX USER/DISK?
UDREQD:
	DB	000H	; ALLOW USER/DISK CHANGE?
PUREQD:
	DB	000H	; PRIVILEGED USER?
CDREQD:
	DB	0FFH	; CURRENT INDIC AND DMA?
NDREQD:
	DB	0FFH	; NAMED DIRECTORIES?
Z2CLASS:
	DB	0	; CLASS 0
	DB	'ZCPR2'
	DS	10	; RESERVED

;
;  END OF SINSFORM -- STANDARD DEFAULT PARAMETER DATA
;
;******************************************************************
;

;
;  Start of Program
;
start:
	lxi	h,0	; save stack
	dad	sp
	shld	stack
	xra	a	; A=0
	sta	chflag	; set no changes
	sta	flflag	; set no file loaded
	sta	ecount	; set no entries
	call	zgpins	; set up environ
	call	print
	db	'MKDIR  Version '
	db	vers/10+'0','.',(vers mod 10)+'0',0
	lda	fcb+1	; check for help
	cpi	'/'
	jnz	start1
	call	print	; print help message
	db	cr,lf,'	MKDIR is used to read and edit named directory files.'
	db	cr,lf,'It is invoked by the following forms --'
	db	cr,lf
	db	cr,lf,'		MKDIR			<-- Enter System'
	db	cr,lf,'		MKDIR dir:filename.typ	<-- Define File First'
	db	cr,lf,'		MKDIR //		<-- Print this Help'
	db	cr,lf,0
	ret

start1:
	call	putud	; save current dir for quick return
	call	retud	; get current user and disk
	mov	a,b	; save disk
	sta	cdisk
	mov	a,c
	sta	cuser
	lxi	h,dnfile	; set default file name
	lxi	d,dfcb+1	; copy into fcb
	mvi	b,11	; 11 chars
	call	moveb
	lxi	h,tbuff	; save command line as string
	call	cline
	call	sblank	; skip to non-blank
	ora	a	; no entry?
	jz	mkdir	; enter system
;
;  Main Entry Point for Loading a File
;
loadfile:
	lxi	sp,stack	; set stack
	lxi	d,dfcb	; set up default file name
	call	zfname	; extract info
	jnz	start2
	call	print
	db	cr,lf,'Error in Disk or User -- Ignoring',0
	lda	cdisk	; set current values
	mov	b,a
	lda	cuser
	mov	c,a
	jmp	start3
start2:
	mov	a,b	; check for current disk
	cpi	0ffh	; current?
	jnz	cutst
	lda	cdisk	; get current disk
	mov	b,a
	inr	b	; add 1 for following decrement
cutst:
	dcr	b	; adjust disk to 0 to n-1
	mov	a,c	; check for current user
	cpi	0ffh	; current?
	jnz	start3
	lda	cuser	; get current user
	mov	c,a
start3:
	call	logud	; log into UD to begin search
;
;  Entry Point for Loading File in DFCB
;
ffile:
	lxi	sp,stack	; reset stack
	mvi	b,0ffh	; search current first
	lxi	d,dfcb	; pt to FCB
	call	initfcb	; init it
	call	zpfind	; look for file
	jnz	start4
	call	print
	db	cr,lf,'File ',0
	lxi	h,dfcb+1	; print name
	call	prfn
	call	print
	db	' Not Found',0
	jmp	mkdir
start4:
	call	logud	; log into dir of file
	lxi	d,dfcb
	call	initfcb
	call	fi0$open	; open file for input
	call	codend	; pt to scratch buffer
	lda	ndnames	; get max entry count
	mov	b,a	; ... in B
readf:
	call	getch	; get disk letter from file
	sui	'A'	; convert to number from 0 to n-1
	mov	m,a	; store disk number
	inx	h	; pt to user number
	call	getch	; get user number
	mov	m,a	; store user number
	inx	h	; pt to next
	mvi	c,8	; store dir name
readn:
	call	getch	; get char
	ora	a	; done?
	jz	readn1
	mov	m,a	; store char if not done
	inx	h	; pt to next
	dcr	c	; count down
	jnz	readn
	jmp	readn2
readn0:
	call	getch	; flush char
readn1:
	mvi	m,' '	; store spaces now
	inx	h	; pt to next
	dcr	c	; count down
	jnz	readn0
readn2:
	call	getch	; flush 9th char
	dcr	b	; count down
	jnz	readf	; continue reading file entries
	call	fi0$close	; close input file
	call	getud	; return to current dir
	call	dirpack	; pack dir
	mvi	a,0ffh	; set file loaded flag
	sta	flflag
	jmp	mkdir1
;
;  Enter MKDIR System and Init Environ
;	Enter at MKDIR if no file loaded, enter at MKDIR1 if file loaded
;
mkdir:
	call	dinit0	; init directory
	xra	a	; A=0
	sta	ecount	; set no entries present
	sta	flflag	; set no file loaded
	sta	chflag	; set no changes
mkdir1:
	lxi	sp,stack	; set stack
	call	print
	db	cr,lf,'MKDIR Command (? for Help)? ',0
	call	cin	; get command
	call	caps	; capitalize
	call	cout	; echo
	lxi	d,mkdir1	; set ret address
	push	d
	lxi	h,ctable	; scan command table for it
	mov	c,a	; command in C
mkdir2:
	mov	a,m	; get command letter
	ora	a	; end of table?
	jz	mkdirh
	cmp	c	; match?
	jz	mkdir3
	inx	h	; skip over address
	inx	h
	inx	h
	jmp	mkdir2
mkdir3:
	inx	h	; get address in HL
	mov	a,m	; low
	inx	h
	mov	h,m
	mov	l,a	; HL is address of routine
	pchl		; "call" routine
;
;  Print MKDIR Command Help
;
mkdirh:
	call	print
	db	cr,lf,'MKDIR Commands are --'
	db	cr,lf,'	C -- Change Directory (Add/Rename/Delete Entries)'
	db	cr,lf,'	I -- Initialize Directory'
	db	cr,lf,'	P -- Print Directory'
	db	cr,lf,'	R -- Read Directory File'
	db	cr,lf,'	S -- Status of MKDIR Environment'
	db	cr,lf,'	W -- Write Directory File'
	db	cr,lf,'	X -- Exit Program'
	db	cr,lf,0
	ret
;
;  Command Table
;
ctable:
	db	'C'	; change directory
	dw	change
	db	'I'	; init directory
	dw	dinit
	db	'P'	; print directory
	dw	dprint
	db	'R'	; read file
	dw	read
	db	'S'	; status
	dw	status
	db	'W'	; write file
	dw	write
	db	'X'	; exit
	dw	exit
	db	0	; end of table
;
;  Status
;
status:
	call	print
	db	cr,lf,'** MKDIR Status **',cr,lf,cr,lf,0
	lda	ecount	; print entry count
	mov	b,a	; ... count in B for later
	call	padc
	call	print
	db	' Entries in Directory',cr,lf,0
	lda	ndnames	; get limit
	sub	b	; subtract amount taken so far
	call	padc
	call	print
	db	' Empty Entries Remaining'
	db	cr,lf
	db	cr,lf,'Working File Name: ',0
	lxi	h,dfcb+1
	call	prfn
	call	crlf	; new line
	call	crlf
	lda	chflag	; changes made?
	ora	a
	jnz	stat1
	call	print
	db	'No ',0
stat1:
	call	print
	db	'Changes made to Directory since Startup'
	db	cr,lf,0
	lda	flflag	; file loaded?
	ora	a	; 0=no
	jnz	stat2
	call	print
	db	'No ',0
stat2:
	call	print
	db	'File has been loaded',cr,lf,0
	ret

;
;  Init Directory
;
dinit:
	call	print
	db	cr,lf,'	Are you sure you want to Initialize the Directory '
	db	'(Y/N/<CR>=N)? ',0
	call	cin	; get response
	call	caps
	call	cout
	call	crlf
	cpi	'Y'	; Yes is only valid reply
	rnz
dinit0:
	xra	a	; A=0
	sta	ecount
	mvi	a,0ffh
	sta	chflag	; set change flag
	call	codend	; pt to directory
	lda	ndnames	; get entry count
	mov	b,a	; ... in B
dinit1:
	mvi	m,0	; set double zero
	inx	h
	mvi	m,0
	inx	h	; pt to name
	mvi	c,8	; 8 chars
dinit2:
	mvi	m,' '	; store space
	inx	h	; pt to next
	dcr	c	; count down
	jnz	dinit2
	dcr	b	; count down
	jnz	dinit1
	ret
;
;  Read File
;
read:
	call	getfname	; get file name
	ora	a		; none?
	jz	ffile		; just find default file and load it
	jmp	loadfile	; parse entry and load file
;
;  Get File Name from User
;
getfname:
	call	print
	db	cr,lf,'Name of File (<RETURN> = ',0
	lxi	h,dfcb+1	; print default name
	call	prfn
	call	print
	db	')? ',0
	mvi	a,0ffh	; capitalize
	call	bbline	; get user input
	call	sblank	; skip to non-blank
	ora	a	; default?
	ret
;
;  Write File
;
write:
	call	getfname
	jz	write1
	lxi	d,dfcb	; parse into DFCB
	call	zfname	; parse file name
	jnz	write0
	call	print
	db	cr,lf,'Invalid Disk or User -- Using Current Directory',0
	jmp	write1
write0:
	mov	a,b	; current disk?
	cpi	0ffh
	jnz	wutst
	lda	cdisk	; select current disk
	mov	b,a
	inr	b	; add 1 for following decrement
wutst:
	dcr	b	; adjust disk to 0 to n-1
	mov	a,c	; current user?
	cpi	0ffh
	jnz	wlog
	lda	cuser	; select current user
	mov	c,a
wlog:
	call	logud	; log into new dir
write1:
	lxi	d,dfcb	; open file for output
	call	initfcb
	call	fo0$open	; open file
	ora	a	; OK?
	jnz	werr	; write error and abort
	call	print
	db	cr,lf,'Writing Directory to Disk ... ',0
	lda	ndnames	; save dir as loaded
	mov	b,a	; count in B
	call	codend	; pt to start of buffer
writef:
	mov	a,m	; get disk
	adi	'A'	; convert to letter
	call	putch	; write char
	inx	h	; pt to user
	mov	a,m	; get user
	call	putch	; write char
	inx	h	; pt to next
	mvi	c,8	; write dir name to disk
wf1:
	mov	a,m	; get char
	cpi	' '	; done?
	jz	wf2
	inx	h	; pt to next
	call	putch	; write char to disk
	dcr	c	; count down
	jnz	wf1
	jmp	wf3
wf2:
	xra	a	; write zeroes
	inx	h	; skip next char
	call	putch
	dcr	c	; count down
	jnz	wf2
wf3:
	xra	a	; write 9th zero
	call	putch
	dcr	b	; count down
	jnz	writef
	call	fo0$close	; close file
	call	getud	; go home
	xra	a	; A=0
	sta	chflag	; set no changes flag
	call	print
	db	'Done',0
	ret
;
;  Exit from MKDIR
;
exit:
	lda	chflag	; check for any changes
	ora	a	; 0=No
	jz	exit1
	call	print
	db	cr,lf
	db	cr,lf,'Directory has changed since last Write'
	db	cr,lf,'Do you want to write Directory to Disk first '
	db	'(Y/N/<CR>=Y)?',0
	call	cin	; get response
	call	caps
	call	cout
	call	crlf	; new line
	cpi	'N'	; no?
	cnz	write	; write if not No
exit1:
	lhld	stack	; return to OS
	sphl
	ret
;
;  Print Directory to User
;
dprint:
	lda	ecount	; any entries?
	ora	a	; 0=none
	jnz	dpr1
	call	print
	db	cr,lf,'Empty Directory',0
	ret
dpr1:
	call	codend	; pt to first element
	lda	ecount	; get entry count
	mov	b,a	; ... in B
	mvi	c,'A'-1	; set disk type
prloop:
	inr	c	; next disk
	call	print
	db	cr,lf,'Disk ',0
	mov	a,c	; print disk letter
	call	cout
	call	print
	db	' --',0
	mvi	a,0ffh	; set line count
	sta	crcnt
prl1:
	mov	a,m	; get next disk
	adi	'A'	; convert to alpha
	cmp	c	; same as current?
	jnz	prloop	; loop to next if not
	lda	crcnt	; increment entry count
	inr	a
	sta	crcnt
	ani	3	; new line?
	cz	crlf
	call	print
	db	'   ',0	; space over
	inx	h	; pt to user
	mov	a,m	; get user number
	call	padc	; print user number
	call	print
	db	': ',0
	inx	h	; pt to name
	mvi	d,8	; 8 chars
prl2:
	mov	a,m	; get char
	inx	h	; pt to next
	call	cout	; print char
	dcr	d	; count down
	jnz	prl2
prl3:
	dcr	b	; count down
	jnz	prl1
	call	crlf	; new line
	lda	ecount
	call	padc
	call	print
	db	' Entries in Directory',0
	ret
;
;  Change Directory Contents
;
change:
	call	print
	db	cr,lf,'** MKDIR Change Mode **',0
ch0:
	call	print
	db	cr,lf,'Directory Entry (?<RETURN> for Help)? ',0
	mvi	a,0ffh	; caps
	call	bbline	; get user input
	call	sblank	; skip to non-blank
	ora	a	; no input?
	jz	chprint	; done, so print directory
	mov	a,m	; get first char
	cpi	'X'	; Exit?
	jz	dsort	; if so, sort and then exit
	cpi	'?'	; help?
	jnz	ch1
	call	print
	db	cr,lf
	db	cr,lf,'MKDIR Change Mode --'
	db	cr,lf,'	You may issue the following commands at this point:'
	db	cr,lf
	db	cr,lf,'		DU:dirname	<-- Create/Rename Dir Entry'
	db	cr,lf,'		DU:		<-- Delete Dir Entry'
	db	cr,lf,'		<RETURN>	<-- Print Directory'
	db	cr,lf,'		X		<-- Exit'
	db	cr,lf,'		?		<-- Print this Help'
	db	cr,lf,0
	jmp	ch0
chprint:
	call	dsort	; use dsort routine
	call	dprint	; use dprint routine
	jmp	ch0	; continue
ch1:
	lxi	d,tfcb	; extract user and disk info as well as name
	call	zfname	; get info
	jnz	ch2
	call	print
	db	cr,lf,'Error in Disk or User',0
	jmp	ch0
ch2:
	mov	a,b	; current disk?
	cpi	0ffh
	jnz	ch3
	lda	cdisk	; set disk
	mov	b,a
	inr	b	; add 1 for following decrement
ch3:
	dcr	b	; adjust disk to 0 to n-1
	mov	a,c	; current user?
	cpi	0ffh
	jnz	ch4
	lda	cuser	; set user
	mov	c,a
ch4:
	mov	a,b	; save as temp disk and user
	sta	tdisk
	mov	a,c
	sta	tuser
;
;  Scan Directory for Temp Disk and User
;
	lda	ndnames	; get entry count
	mov	b,a	; ... in B
	call	codend	; pt to first entry
scanud:
	inx	h	; pt to name
	inx	h
	mov	a,m	; get first char of name
	dcx	h
	dcx	h	; pt to disk
	cpi	' '	; deleted entry?
	jz	scanud1
	mov	d,m	; get disk
	lda	tdisk	; compare it
	cmp	d
	jnz	scanud1
	inx	h	; pt to user
	mov	a,m	; get user
	dcx	h	; pt back
	cmp	c	; compare it
	jz	udfound
scanud1:
	lxi	d,10	; pt to next
	dad	d
	dcr	b	; count down
	jnz	scanud
	lda	tfcb+1	; delete?
	cpi	'?'	; ? if so
	jnz	addname
	call	print
	db	cr,lf,'	-- DU not found for Delete -- No Change Made',0
	jmp	ch0
;
;  Found Possible Directory Entry
;
udfound:
	inx	h	; found existing entry
	inx	h	; pt to name
	lda	tfcb+1	; delete?
	cpi	'?'	; ? if so
	jz	delname
;
;  Rename Function
;
	xra	a	; clear add flag
	sta	addflg
	call	print
	db	cr,lf,'	Renaming ',0
	mvi	b,8	; 8 chars
	push	h	; save ptr
	call	prfn1	; print name
	pop	h	; get ptr
	mvi	m,' '	; space fill
	jmp	putname
;
;  Add Function
;
addname:
	mvi	a,0ffh	; set add flag
	sta	addflg
	call	print
	db	cr,lf,'	Adding ',0
	lxi	h,tfcb+1
	mvi	b,8
	call	prfn1
	lda	ecount	; increment entry count
	inr	a
	sta	ecount
putname:
	lda	ndnames	; get entry count
	mov	c,a	; ... in C
	call	codend	; pt to first entry
	inx	h	; pt to name
	inx	h
etest:
	lxi	d,tfcb+1	; pt to new name
	mvi	b,8	; 8 chars
	call	compb	; compare
	jnz	etest1
	call	print
	db	cr,lf,'	-- Error -- Duplicate Name Exists -- No Change Made',0
	lda	addflg	; add?
	ora	a	; 0=no
	jz	ch0
	lda	ecount	; count down
	dcr	a
	sta	ecount
	jmp	ch0
etest1:
	lxi	d,10	; pt to next entry
	dad	d
	dcr	c	; count down
	jnz	etest
	mvi	a,0ffh	; change made
	sta	chflag
	lda	ndnames	; get entry count
	mov	b,a	; ... in B
	call	codend	; pt to first
	inx	h	; pt to name
	inx	h
putn1:
	mov	a,m	; valid entry?
	cpi	' '	; empty?
	jnz	putn2
	dcx	h	; pt to disk
	dcx	h
	lda	tdisk
	mov	m,a
	inx	h
	lda	tuser
	mov	m,a
	inx	h
	lxi	d,tfcb+1	; pt to new name
	xchg
	mvi	b,8	; 8 chars
	call	moveb
	call	print
	db	' -- ',0
	lda	ecount	; print count
	mov	b,a	; ... in B
	call	padc
	call	print
	db	' Entries in Directory, Room for ',0
	lda	ndnames
	sub	b
	call	padc
	call	print
	db	' More',0
	jmp	ch0	; continue
putn2:
	lxi	d,10	; skip to next entry
	dad	d
	dcr	b	; count down
	jnz	putn1
	call	print
	db	cr,lf,'** Directory Full **',0
	lda	addflg	; adding?
	ora	a	; 0=no
	jz	ch0
	lda	ecount	; count down
	dcr	a
	sta	ecount
	jmp	ch0
;
;  Delete Function
;
delname:
	mvi	a,0ffh	; change made
	sta	chflag
	call	print
	db	cr,lf,'	Deleting ',0
	mvi	b,8	; 8 chars
	push	h	; save ptr
	call	prfn1
	pop	h	; get ptr
	mvi	m,' '	; space fill
	call	dirpack	; pack directory
	call	print
	db	' -- ',0
	lda	ecount	; print remaining count
	call	padc
	call	print
	db	' Entries Remaining',0
	jmp	ch0	; continue
;
;  Sort Directory
;
dsort:
	call	dirpack	; pack directory
	lda	ecount	; number of elements
	ora	a	; any?
	rz		; done if none
	sta	ssbcnt	; set count
	call	codend	; pt to first element
	shld	ssbstrt	; set starting address
	lxi	d,ssb	; pt to sort specifiction block
	call	sort	; sort
	ret
;
;  Sort Compare Routine
;
compare:
	push	h	; don't change regs
	push	d
	ldax	d	; compare disk
	cmp	m
	jnz	comp1
	inx	h	; pt to user
	inx	d
	ldax	d	; compare user
	cmp	m
comp1:
	pop	d	; restore regs
	pop	h
	ret

;
;  Utilities
;

;
;  Read and Write Chars to Disk
;
getch:
	call	f0$get	; get char
	rz		; OK since no error
	call	print
	db	cr,lf,'File Read Error -- Aborting',0
	jmp	mkdir1	; goto command level
putch:
	call	f0$put	; put char
	rz		; OK since no error
werr:
	call	print
	db	cr,lf,'Disk Write Error -- Aborting',0
	call	getud	; return home
	jmp	mkdir1
;
;  Pack Memory-Based Directory
;
dirpack:
	call	codend	; get address of first entry
	mov	d,h	; DE pts to it also
	mov	e,l
	lda	ndnames	; get max count
	mov	b,a	; ... in B
	mvi	c,0	; set entry count
dirp0:
	push	b	; save counts
	inx	h	; pt to name
	inx	h
	mov	a,m	; get char
	dcx	h	; pt back to disk
	dcx	h
	cpi	' '	; no entry if space
	jz	dirp1
	mvi	b,10	; copy 10 bytes
dirpm:
	mov	a,m	; copy HL to DE for B bytes
	stax	d
	inx	h	; pt to next
	inx	d
	dcr	b	; count down
	jnz	dirpm
	pop	b	; get counts
	inr	c	; 1 more entry
	jmp	dirp2
dirp1:
	push	d	; save new entry ptr
	lxi	d,10	; pt to next entry
	dad	d
	pop	d
	pop	b	; get counts
dirp2:
	dcr	b	; count down
	jnz	dirp0
	mov	a,c	; save count
	sta	ecount
	lda	ndnames	; make rest empty
	sub	c	; number of entries remaining
	mov	b,a	; ... in B
	ora	a	; none?
	rz
	xchg		; HL pts to next entry
	inx	h	; pt to name
	inx	h
	lxi	d,10	; prep to add 10
dirp3:
	mvi	m,' '	; set space as first char
	dad	d	; pt to next
	dcr	b	; count down
	jnz	dirp3
	ret
;
;  Skip until non-blank encountered
;
sblank:
	mov	a,m	; get char
	inx	h	; pt to next
	cpi	' '	; skip space
	jz	sblank
	dcx	h	; pt to char
	ret
;
;  Print file name pted to by HL
;
prfn:
	push	b	; save regs
	push	h
	mvi	b,8	; 8 chars
	call	prfn1
	mvi	a,'.'
	call	cout
	mvi	b,3	; 3 chars
	call	prfn1
	pop	h	; get regs
	pop	b
	ret
prfn1:
	mov	a,m	; print chars
	inx	h	; pt to next
	call	cout
	dcr	b	; count down
	jnz	prfn1
	ret

;
;  Sort Specification Block
;
ssb:
ssbstrt:
	ds	2	; start address of dir
ssbcnt:
	dw	0	; number of records to sort
	dw	10	; 10 bytes/record
	dw	compare	; compare routine
	dw	0	; no ptr table
	db	0,0	; don't use ptrs
;
;  Buffers
;
cdisk:
	ds	1	; current disk
cuser:
	ds	1	; current user
tdisk:
	ds	1	; temp disk
tuser:
	ds	1	; temp user
flflag:
	ds	1	; file loaded flag
chflag:
	ds	1	; dir changed flag
ecount:
	ds	1	; entry count
addflg:
	ds	1	; add/rename flag
crcnt:
	ds	1	; new line count
tfcb:
	ds	36	; temp FCB
dfcb:
	ds	36	; Default FCB
	ds	50	; 25-elt stack
stack:
	ds	2	; original stack ptr

	end
